//************************************************************************************************************
// CoNatural.Data.dll
// Author: Roger Torres
//************************************************************************************************************
// You can use, modify, and distribute the source code and executable programs based on the source code.
// This source code is provided "as is" and without warranties as to performance or merchantability. 
// The author and/or distributors of this source code may have made statements about this source code. 
// Any such statements do not constitute warranties and shall not be relied on by the user in deciding 
// whether to use this source code. This source code is provided without any express or implied warranties 
// whatsoever. Because of the diversity of conditions and hardware under which this source code may be used, 
// no warranty of fitness for a particular purpose is offered. The user is advised to test the source code 
// thoroughly before relying on it. The user must assume the entire risk of using the source code.
//************************************************************************************************************

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Transactions;
using System.Text;

namespace CoNatural.Data {
   /// <summary>
   /// Basic command deployer class.
   /// </summary>
   public abstract class CommandDeployerBase : ICommandDeployer {
      public abstract void DeployCommands(IConnection connection, IEnumerable<ICommand> iCommands);

      #region ICommandDeployer Members

      public void Deploy(IConnection connection, Assembly assembly) {
         Deploy(connection, GetCommands(assembly));
      }

      public void Deploy(IConnection connection, IEnumerable<ICommand> iCommands) {
         using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress)) {
            try {
               DeployCommands(connection, iCommands);
            }
            catch (Exception ex) {
               StringBuilder sb = new StringBuilder();
               while (ex != null) {
                  sb.AppendLine(ex.Message);
                  ex = ex.InnerException;
               }
               throw new Exception(sb.ToString());
            }
            scope.Complete();
         }
      }

		public void Deploy(IConnection connection, params ICommand[] iCommands) {
			Deploy(connection, iCommands as IEnumerable<ICommand>);
		}

      #endregion

      /// <summary>
      /// Helper to enumerate commands embedded in assembly
      /// </summary>
      /// <param name="assembly">The assembly.</param>
      /// <returns>The enumeration.</returns>
      private IEnumerable<ICommand> GetCommands(System.Reflection.Assembly assembly) {
         foreach (Type type in assembly.GetTypes())
            if (type.IsClass && !type.IsAbstract && type.GetInterface("ICommand") != null) {
               ICommand command = (ICommand)Activator.CreateInstance(type);
               yield return command;
            }
      }
   }
}
